// src/main/utils/projectManager.js

const fs = require('fs').promises
const path = require('path')
let uuidv4;
try {
  uuidv4 = require('uuid').v4;
} catch (error) {
  // 如果UUID模块不可用，使用简单的ID生成
  uuidv4 = () => Date.now().toString(36) + Math.random().toString(36).substring(2, 11);
}

class ProjectManager {
  constructor() {
    this.projectsDir = null
    this.configDir = null
    // 全局配置目录 - 存储在项目根目录下
    this.globalConfigDir = path.join(__dirname, '../../../.deep-learning-platform')
  }

  /**
   * 初始化项目管理器，设置工作目录
   * @param {string} workspaceDir - 用户选择的工作目录
   */
  async initialize(workspaceDir) {
    this.projectsDir = path.join(workspaceDir, 'projects')
    this.configDir = path.join(workspaceDir, '.deep-learning-platform')
    
    // 确保目录存在
    await this.ensureDirectories()
  }

  /**
   * 确保必要的目录结构存在
   */
  async ensureDirectories() {
    const dirs = [
      this.projectsDir,
      this.configDir,
      this.globalConfigDir  // 确保全局配置目录存在
    ]
    
    for (const dir of dirs) {
      if (dir) {  // 只处理非空目录
        try {
          await fs.access(dir)
        } catch (error) {
          if (error.code === 'ENOENT') {
            await fs.mkdir(dir, { recursive: true })
            console.log(`[ProjectManager] 创建目录: ${dir}`)
          }
        }
      }
    }
  }

  /**
   * 创建新项目
   * @param {Object} projectData - 项目配置数据
   * @returns {Object} 创建结果
   */
  async createProject(projectData) {
    console.log('[ProjectManager] 开始创建项目:', projectData)
    console.log('[ProjectManager] 项目目录:', this.projectsDir)
    
    if (!this.projectsDir) {
      throw new Error('项目管理器未初始化，请先调用 initialize() 方法')
    }
    
    try {
      const projectId = uuidv4()
      const projectName = projectData.name
      const projectPath = path.join(this.projectsDir, projectName)
      
      console.log('[ProjectManager] 项目ID:', projectId)
      console.log('[ProjectManager] 项目路径:', projectPath)
      
      // 检查项目名是否已存在
      try {
        await fs.access(projectPath)
        throw new Error(`项目 "${projectName}" 已存在`)
      } catch (error) {
        if (error.code !== 'ENOENT') {
          throw error
        }
      }
      
      // 创建项目目录结构
      await this.createProjectStructure(projectPath)
      
      // 生成项目配置 - 兼容前端显示格式
      const projectConfig = {
        // 前端期望的顶级字段
        id: projectId,
        name: projectName,
        description: projectData.description || '',
        path: projectPath,
        instance: projectData.instance,
        method: this.getProjectMethod(projectData.instance?.id),
        images: [],
        types: [],
        tags: [],
        version: {
          program: '1.0.0',
          file: '1.0.0'
        },
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
        
        // 标准化项目配置结构
        configVersion: "1.0",
        project: {
          id: projectId,
          name: projectName,
          description: projectData.description || '',
          type: this.getProjectType(projectData.instance?.id),
          created_at: new Date().toISOString(),
          updated_at: new Date().toISOString(),
          author: process.env.USER || process.env.USERNAME || 'unknown',
          version: "1.0.0"
        },
        settings: {
          image_formats: ["jpg", "jpeg", "png", "bmp", "tiff", "webp"],
          annotation_format: "coco",
          auto_save: true,
          auto_backup: true,
          backup_interval: 300,
          thumbnail_size: 256
        },
        categories: [],
        statistics: {
          total_images: 0,
          annotated_images: 0,
          total_annotations: 0,
          categories_count: {},
          last_annotation_time: null
        },
        paths: {
          images: "images/raw",
          annotations: "annotations",
          models: "models",
          datasets: "datasets",
          logs: "logs",
          cache: "cache",
          backups: "backups"
        }
      }
      
      // 保存项目配置文件
      const configPath = path.join(projectPath, 'project.json')
      await fs.writeFile(configPath, JSON.stringify(projectConfig, null, 2))
      
      // 更新最近项目列表
      await this.updateRecentProjects(projectConfig)
      
      console.log(`[ProjectManager] 项目创建成功: ${projectName}`)
      
      return {
        success: true,
        project: {
          ...projectConfig,
          path: projectPath
        }
      }
    } catch (error) {
      console.error('[ProjectManager] 创建项目失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 创建项目目录结构
   * @param {string} projectPath - 项目根目录路径
   */
  async createProjectStructure(projectPath) {
    const directories = [
      'images/raw',
      'images/processed/resized',
      'images/processed/augmented',
      'annotations/coco',
      'annotations/yolo/labels',
      'annotations/pascal_voc/annotations',
      'datasets',
      'models/checkpoints',
      'models/configs',
      'models/exports',
      'logs/training',
      'logs/annotation',
      'logs/system',
      'cache/thumbnails',
      'cache/metadata',
      'backups'
    ]
    
    for (const dir of directories) {
      const fullPath = path.join(projectPath, dir)
      await fs.mkdir(fullPath, { recursive: true })
    }
    
    // 创建初始配置文件
    const initialFiles = [
      {
        path: 'images/metadata.json',
        content: { images: [] }
      },
      {
        path: 'annotations/annotations.json',
        content: {
          info: {
            description: "深度学习标注数据集",
            version: "1.0",
            created_at: new Date().toISOString()
          },
          categories: [],
          images: [],
          annotations: []
        }
      },
      {
        path: 'datasets/split-config.json',
        content: {
          split_strategy: "random",
          split_ratios: { train: 0.7, val: 0.2, test: 0.1 },
          seed: 42,
          stratified: true,
          min_samples_per_category: 5
        }
      }
    ]
    
    for (const file of initialFiles) {
      const filePath = path.join(projectPath, file.path)
      await fs.writeFile(filePath, JSON.stringify(file.content, null, 2))
    }
  }

  /**
   * 加载项目
   * @param {string} projectPath - 项目路径
   * @returns {Object} 项目配置
   */
  async loadProject(projectPath) {
    try {
      const configPath = path.join(projectPath, 'project.json')
      const configData = await fs.readFile(configPath, 'utf8')
      const projectConfig = JSON.parse(configData)
      
      // 添加项目路径信息
      projectConfig.path = projectPath
      
      // 确保顶级字段存在（向前兼容）
      if (!projectConfig.id && projectConfig.project) {
        projectConfig.id = projectConfig.project.id
        projectConfig.name = projectConfig.project.name
        projectConfig.description = projectConfig.project.description
      }
      
      // 确保必要的数组字段存在
      if (!projectConfig.images) projectConfig.images = []
      if (!projectConfig.types) projectConfig.types = []
      if (!projectConfig.tags) projectConfig.tags = []
      if (!projectConfig.version) {
        projectConfig.version = {
          program: '1.0.0',
          file: '1.0.0'
        }
      }
      
      // 更新最近访问时间
      if (projectConfig.project) {
        projectConfig.project.updated_at = new Date().toISOString()
      }
      projectConfig.updatedAt = new Date().toISOString()
      
      // 更新最近项目列表
      await this.updateRecentProjects(projectConfig)
      
      console.log(`[ProjectManager] 项目加载成功: ${projectConfig.name || projectConfig.project?.name}`)
      return {
        success: true,
        project: projectConfig
      }
    } catch (error) {
      console.error('[ProjectManager] 加载项目失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 保存项目配置
   * @param {Object} projectConfig - 项目配置
   * @returns {Object} 保存结果
   */
  async saveProject(projectConfig) {
    try {
      const projectPath = projectConfig.path
      const configPath = path.join(projectPath, 'project.json')
      
      
      // 确保项目配置结构正确
      if (!projectConfig.project) {
        projectConfig.project = {
          id: projectConfig.id,
          name: projectConfig.name,
          description: projectConfig.description,
          created_at: projectConfig.createdAt || new Date().toISOString(),
          updated_at: new Date().toISOString()
        }
      }
      
      // 更新修改时间
      projectConfig.project.updated_at = new Date().toISOString()
      projectConfig.updatedAt = new Date().toISOString()
      
      // 保存配置文件
      await fs.writeFile(configPath, JSON.stringify(projectConfig, null, 2))
      
      // 更新最近项目列表
      await this.updateRecentProjects(projectConfig)
      
      console.log(`[ProjectManager] 项目保存成功: ${projectConfig.project.name || projectConfig.name}`)
      return { success: true }
    } catch (error) {
      console.error('[ProjectManager] 保存项目失败:', error)
      console.error('[ProjectManager] 项目配置结构:', projectConfig)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 获取最近项目列表
   * @returns {Array} 最近项目列表
   */
  async getRecentProjects() {
    try {
      // 确保全局配置目录存在
      await this.ensureDirectories()
      
      const recentProjectsPath = path.join(this.globalConfigDir, 'recent-projects.json')
      
      let recentProjects = []
      try {
        const data = await fs.readFile(recentProjectsPath, 'utf8')
        const projectData = JSON.parse(data)
        recentProjects = projectData.projects || []
      } catch (error) {
        if (error.code === 'ENOENT') {
          console.log('[ProjectManager] 最近项目文件不存在，返回空列表')
          return []
        }
        throw error
      }
      
      // 验证每个项目是否仍然存在，并更新状态
      const validatedProjects = []
      for (const project of recentProjects) {
        const projectCopy = { ...project }
        const projectConfigPath = path.join(project.path, 'project.json')
        
        try {
          // 检查项目文件是否存在
          await fs.access(projectConfigPath)
          projectCopy.exists = true
          projectCopy.status = 'available'
        } catch (error) {
          // 项目不存在，标记为已移除
          projectCopy.exists = false
          projectCopy.status = 'removed'
          projectCopy.name = `${project.name || '未知项目'} (已移除)`
        }
        
        validatedProjects.push(projectCopy)
      }
      
      console.log(`[ProjectManager] 获取到 ${validatedProjects.length} 个最近项目，其中 ${validatedProjects.filter(p => p.exists).length} 个可用`)
      return validatedProjects
      
    } catch (error) {
      console.error('[ProjectManager] 获取最近项目失败:', error)
      return []
    }
  }

  /**
   * 更新最近项目列表
   * @param {Object} projectConfig - 项目配置
   */
  async updateRecentProjects(projectConfig) {
    try {
      // 确保全局配置目录存在
      await this.ensureDirectories()
      
      const recentProjectsPath = path.join(this.globalConfigDir, 'recent-projects.json')
      
      let recentProjects = []
      try {
        const data = await fs.readFile(recentProjectsPath, 'utf8')
        const existingData = JSON.parse(data)
        recentProjects = existingData.projects || []
      } catch (error) {
        // 文件不存在，使用空数组
      }
      
      // 移除已存在的项目（基于项目路径）
      const currentProjectPath = projectConfig.path
      recentProjects = recentProjects.filter(p => p.path !== currentProjectPath)
      
      // 创建项目记录 - 只保存必要的信息和路径
      const projectRecord = {
        id: projectConfig.id || projectConfig.project?.id,
        name: projectConfig.name || projectConfig.project?.name,
        description: projectConfig.description || projectConfig.project?.description,
        path: currentProjectPath,
        instance: projectConfig.instance,
        method: projectConfig.method,
        version: projectConfig.version,
        createdAt: projectConfig.createdAt || projectConfig.project?.created_at,
        updatedAt: new Date().toISOString(),
        last_opened: new Date().toISOString(),
        exists: true,
        status: 'available'
      }
      
      // 添加到列表开头
      recentProjects.unshift(projectRecord)
      
      // 限制列表长度为10
      if (recentProjects.length > 10) {
        recentProjects = recentProjects.slice(0, 10)
      }
      
      // 保存更新后的列表
      const updatedData = {
        version: "1.0",
        updated_at: new Date().toISOString(),
        projects: recentProjects
      }
      
      await fs.writeFile(recentProjectsPath, JSON.stringify(updatedData, null, 2))
      console.log(`[ProjectManager] 已更新最近项目列表，当前有 ${recentProjects.length} 个项目`)
    } catch (error) {
      console.error('[ProjectManager] 更新最近项目失败:', error)
    }
  }

  /**
   * 导入图像到项目
   * @param {string} projectPath - 项目路径
   * @param {Array} imagePaths - 图像文件路径数组
   * @returns {Object} 导入结果
   */
  async importImages(projectPath, imagePaths) {
    try {
      const imagesDir = path.join(projectPath, 'images', 'raw')
      const metadataPath = path.join(projectPath, 'images', 'metadata.json')
      
      // 读取现有元数据
      let metadata = { images: [] }
      try {
        const data = await fs.readFile(metadataPath, 'utf8')
        metadata = JSON.parse(data)
      } catch (error) {
        // 文件不存在，使用默认值
      }
      
      const importedImages = []
      
      for (const imagePath of imagePaths) {
        const fileName = path.basename(imagePath)
        const fileExt = path.extname(fileName).toLowerCase()
        const baseName = path.basename(fileName, fileExt)
        
        // 生成唯一文件名（如果重复）
        let uniqueFileName = fileName
        let counter = 1
        while (metadata.images.some(img => img.filename === uniqueFileName)) {
          uniqueFileName = `${baseName}_${counter}${fileExt}`
          counter++
        }
        
        const targetPath = path.join(imagesDir, uniqueFileName)
        
        // 复制文件
        await fs.copyFile(imagePath, targetPath)
        
        // 获取文件信息
        const stats = await fs.stat(targetPath)
        
        // 获取图片尺寸
        let width = null, height = null
        try {
          // 尝试使用sharp获取图片尺寸
          const sharp = require('sharp')
          const metadata = await sharp(targetPath).metadata()
          width = metadata.width
          height = metadata.height
        } catch (error) {
          // 尝试使用基础方法读取图片头部信息
          try {
            const dimensions = await this.getImageDimensionsBasic(targetPath)
            width = dimensions.width
            height = dimensions.height
          } catch (basicError) {
            console.warn(`[ProjectManager] 无法获取图片尺寸: ${basicError.message}`)
          }
        }
        
        // 添加到元数据
        const imageMetadata = {
          id: `img_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
          filename: uniqueFileName,
          original_name: fileName,
          path: `images/raw/${uniqueFileName}`,
          width: width,
          height: height,
          file_size: stats.size,
          format: fileExt.substring(1).toUpperCase(),
          created_at: stats.birthtime.toISOString(),
          imported_at: new Date().toISOString(),
          checksum: null, // 可以添加文件校验和
          is_annotated: false,
          annotation_count: 0,
          tags: [],
          quality_score: null,
          processing_status: "imported"
        }
        
        metadata.images.push(imageMetadata)
        importedImages.push(imageMetadata)
      }
      
      // 保存更新后的元数据
      await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2))
      
      console.log(`[ProjectManager] 成功导入 ${importedImages.length} 张图像`)
      
      return {
        success: true,
        imported: importedImages.length,
        images: importedImages
      }
    } catch (error) {
      console.error('[ProjectManager] 导入图像失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 根据深度学习方法ID获取项目类型
   * @param {number} instanceId - 方法ID
   * @returns {string} 项目类型
   */
  getProjectType(instanceId) {
    const typeMap = {
      1: 'classification',      // 分类
      2: 'anomaly_detection',   // 异常检测
      3: 'object_detection',    // 目标检测
      4: 'instance_segmentation', // 实例分割
      5: 'defect_generation'    // 缺陷生成
    }
    return typeMap[instanceId] || 'classification'
  }

  /**
   * 删除项目
   * @param {string} projectPath - 项目路径
   * @returns {Object} 删除结果
   */
  async deleteProject(projectPath) {
    try {
      console.log('[ProjectManager] 开始删除项目:', projectPath)
      
      if (!projectPath) {
        throw new Error('项目路径不能为空')
      }
      
      // 检查项目是否存在
      try {
        await fs.access(projectPath)
      } catch (error) {
        if (error.code === 'ENOENT') {
          console.log('[ProjectManager] 项目目录不存在，可能已被删除')
          // 即使目录不存在，也要从最近项目列表中移除
          await this.removeFromRecentProjects(projectPath)
          return { success: true, message: '项目已删除（目录不存在）' }
        }
        throw error
      }
      
      // 删除项目目录及所有内容
      await fs.rm(projectPath, { recursive: true, force: true })
      
      // 从最近项目列表中移除
      await this.removeFromRecentProjects(projectPath)
      
      console.log(`[ProjectManager] 项目删除成功: ${projectPath}`)
      return { success: true, message: '项目删除成功' }
      
    } catch (error) {
      console.error('[ProjectManager] 删除项目失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 从最近项目列表中移除项目
   * @param {string} projectPath - 项目路径
   */
  async removeFromRecentProjects(projectPath) {
    try {
      // 确保全局配置目录存在
      await this.ensureDirectories()
      
      const recentProjectsPath = path.join(this.globalConfigDir, 'recent-projects.json')
      
      let recentProjects = []
      try {
        const data = await fs.readFile(recentProjectsPath, 'utf8')
        const existingData = JSON.parse(data)
        recentProjects = existingData.projects || []
      } catch (error) {
        // 文件不存在，无需处理
        return
      }
      
      // 过滤掉要删除的项目
      const filteredProjects = recentProjects.filter(p => p.path !== projectPath)
      
      // 保存更新后的列表
      const updatedData = {
        version: "1.0",
        updated_at: new Date().toISOString(),
        projects: filteredProjects
      }
      
      await fs.writeFile(recentProjectsPath, JSON.stringify(updatedData, null, 2))
      console.log(`[ProjectManager] 已从最近项目列表中移除: ${projectPath}`)
      
    } catch (error) {
      console.error('[ProjectManager] 从最近项目列表移除失败:', error)
    }
  }

  /**
   * 根据深度学习方法ID获取项目方法
   * @param {number} instanceId - 方法ID
   * @returns {string} 项目方法
   */
  getProjectMethod(instanceId) {
    const methodMap = {
      1: '分类',
      2: '异常检测',
      3: '目标检测',
      4: '实例分割',
      5: '缺陷生成'
    }
    return methodMap[instanceId] || '分类'
  }

  /**
   * 获取本地方法配置
   * @returns {Object} 方法配置数据  
   */
  async getLocalMethods() {
    try {
      // 确保全局配置目录存在
      await this.ensureDirectories()
      
      const methodsConfigPath = path.join(this.globalConfigDir, 'local-methods.json')
      
      try {
        const data = await fs.readFile(methodsConfigPath, 'utf8')
        const methodsConfig = JSON.parse(data)
        
        return {
          success: true,
          config: methodsConfig
        }
      } catch (error) {
        if (error.code === 'ENOENT') {
          return {
            success: true,
            config: this.getDefaultMethodsConfig()
          }
        }
        throw error
      }
      
    } catch (error) {
      console.error('[ProjectManager] 获取方法配置失败:', error)
      return {
        success: false,
        error: error.message,
        config: this.getDefaultMethodsConfig()
      }
    }
  }

  /**
   * 基础方法获取图片尺寸（不依赖Sharp）
   * @param {string} imagePath - 图片文件路径
   * @returns {Promise<Object>} 包含width和height的对象
   */
  async getImageDimensionsBasic(imagePath) {
    const buffer = await fs.readFile(imagePath)
    
    // 检测文件类型并读取尺寸
    if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && buffer[3] === 0x47) {
      // PNG format
      const width = buffer.readUInt32BE(16)
      const height = buffer.readUInt32BE(20)
      return { width, height }
    } else if (buffer[0] === 0xFF && buffer[1] === 0xD8) {
      // JPEG format
      let offset = 2
      while (offset < buffer.length) {
        if (buffer[offset] === 0xFF) {
          const marker = buffer[offset + 1]
          if (marker === 0xC0 || marker === 0xC2) {
            const height = buffer.readUInt16BE(offset + 5)
            const width = buffer.readUInt16BE(offset + 7)
            return { width, height }
          }
          const segmentLength = buffer.readUInt16BE(offset + 2)
          offset += 2 + segmentLength
        } else {
          offset++
        }
      }
    }
    
    throw new Error('不支持的图片格式或无法解析图片尺寸')
  }

  /**
   * 获取默认方法配置（兜底配置）
   * @returns {Object} 默认配置
   */
  getDefaultMethodsConfig() {
    return {
      version: "1.0",
      methods: [
        {
          id: 1,
          title: "分类",
          description: "图像分类",
          icon: "📊",
          color: "#409EFF",
          content: "从给定类别集合中将图像分类至其中一个类别。"
        },
        {
          id: 2,
          title: "异常检测",
          description: "全局上下文异常值检测",
          icon: "🔍",
          color: "#F56C6C",
          content: "识别图像中不符合正常模式的异常区域或整体异常。"
        },
        {
          id: 3,
          title: "目标检测",
          description: "轴对齐矩形边界框检测",
          icon: "🎯",
          color: "#67C23A",
          content: "在图像中定位并识别多个目标对象的位置和类别。"
        },
        {
          id: 4,
          title: "实例分割",
          description: "像素级精确分割",
          icon: "✂️",
          color: "#E6A23C",
          content: "不仅检测目标对象，还要分割出每个实例的精确像素级轮廓。"
        },
        {
          id: 5,
          title: "缺陷生成",
          description: "基于AI的缺陷样本生成",
          icon: "⚡",
          color: "#909399",
          content: "利用生成对抗网络等技术生成各种缺陷样本。"
        }
      ],
      data_sources: [
        {
          id: 1,
          title: "导入数据集",
          description: "从现有JSON数据集创建项目",
          icon: "📁",
          color: "#909399",
          content: "从现有json数据集创建项目。数据集定义支持的json方法。"
        }
      ]
    }
  }
}

module.exports = new ProjectManager()